package com.okilo.online.app.tools.log

import java.util.regex.Pattern

class JsonFormat {

    companion object {
        /**
         * 默认每次缩进两个空格
         */
        private const val EMPTY = "  "

        fun format(json: String): String {
            val processedJson = unicodeToString(json)
            try {
                var indentLevel = 0
                val chs = processedJson.toCharArray()
                val stringBuilder = StringBuilder()
                var i = 0
                while (i < chs.size) {
                    // 若是双引号，则为字符串，下面if语句会处理该字符串
                    if (chs[i] == '\"') {
                        stringBuilder.append(chs[i])
                        i++
                        // 查找字符串结束位置
                        while (i < chs.size) {
                            // 如果当前字符是双引号，且前面有连续的偶数个\，说明字符串结束
                            if (chs[i] == '\"' && isDoubleSerialBackslash(chs, i - 1)) {
                                stringBuilder.append(chs[i])
                                i++
                                break
                            } else {
                                stringBuilder.append(chs[i])
                                i++
                            }
                        }
                    } else if (chs[i] == ',') {
                        stringBuilder.append(',').append('\n').append(getEmpty(indentLevel))
                        i++
                    } else if (chs[i] == '{' || chs[i] == '[') {
                        indentLevel++
                        stringBuilder.append(chs[i]).append('\n').append(getEmpty(indentLevel))
                        i++
                    } else if (chs[i] == '}' || chs[i] == ']') {
                        indentLevel--
                        stringBuilder.append('\n').append(getEmpty(indentLevel)).append(chs[i])
                        i++
                    } else {
                        stringBuilder.append(chs[i])
                        i++
                    }
                }
                return stringBuilder.toString()
            } catch (e: Exception) {
                e.printStackTrace()
                return processedJson
            }
        }

        private fun isDoubleSerialBackslash(chs: CharArray, i: Int): Boolean {
            var count = 0
            var j = i
            while (j > -1) {
                if (chs[j] == '\\') {
                    count++
                } else {
                    return count % 2 == 0
                }
                j--
            }
            return count % 2 == 0
        }

        /**
         * 缩进
         */
        private fun getEmpty(count: Int): String {
            val stringBuilder = StringBuilder()
            for (i in 0 until count) {
                stringBuilder.append(EMPTY)
            }
            return stringBuilder.toString()
        }

        fun unicodeToString(str: String): String {
            var result = str
            val pattern = Pattern.compile("(\\\\u(\\p{XDigit}{4}))")
            val matcher = pattern.matcher(result)
            while (matcher.find()) {
                val ch = matcher.group(2).toInt(16).toChar()
                result = result.replace(matcher.group(1), ch.toString())
            }
            return result
        }
    }
}
